package org.micode.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
public class LocalDateUtils {

    public static final String DATE_FORMAT_MILLISECOND_STRING = "yyyy-MM-dd HH:mm:ss.SSS";
    public static final String DATE_FORMAT_SECOND_STRING = "yyyy-MM-dd HH:mm:ss";
    public static final String YYYYMMDD_STRING = "yyyyMMdd";

    public static int quarterValue() {
        return quarterValue(LocalDate.now());
    }

    public static int quarterValue(LocalDate theDate) {
        return (theDate.getMonthValue() - 1) / 3 + 1;
    }

    public static LocalDateTime fromYYYYMMDDhhmm(long longTime) {
        return LocalDateTime.of(
                (int) (longTime / 100000000),
                (int) (longTime / 1000000 % 100),
                (int) (longTime / 10000 % 100),
                (int) (longTime / 100 % 100),
                (int) (longTime % 100),
                0, 0);
    }

    public static long toYYYYMMDDhhmm(LocalDateTime dateTime) {
        return (long) dateTime.getYear() * 100000000 +
                dateTime.getMonthValue() * 1000000 +
                dateTime.getDayOfMonth() * 10000 +
                dateTime.getHour() * 100 +
                dateTime.getMinute();
    }

    public static LocalDateTime secondDateTime(LocalDateTime dt) {
        return LocalDateTime.of(
                dt.getYear(),
                dt.getMonthValue(),
                dt.getDayOfMonth(),
                dt.getHour(),
                dt.getMinute(),
                dt.getSecond()
        );
    }

    public static long betweenDays(LocalDate begin, LocalDate end) {
        Duration duration = Duration.between(
                begin.atTime(0, 0, 0),
                end.atTime(0, 0, 0));
        return duration.toDays();
    }

    public static long betweenHours(LocalDateTime begin, LocalDateTime end) {
        Duration duration = Duration.between(begin, end);
        return duration.toHours();
    }

    public static Integer yyyymm(LocalDate inDate) {
        if (inDate != null) {
            return inDate.getYear() * 100 + inDate.getMonthValue();
        }
        return null;
    }

    public static LocalDateTime zeroHourForDate(LocalDateTime inDate) {
        if (inDate != null) {
            return inDate.toLocalDate().atTime(0, 0, 0);
        }
        return null;
    }

    public static String currentDateTime64String() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(DATE_FORMAT_MILLISECOND_STRING));
    }

    public static String currentDatetimeString() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(DATE_FORMAT_SECOND_STRING));
    }

    public static String strYYYYMMDD() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(YYYYMMDD_STRING));
    }

    /**
     * 按照参数format的格式，日期转字符串
     *
     * @param date   要转换的日期
     * @param format 转换格式
     * @return 转换结果字符串
     */
    public static String date2Str(LocalDateTime date, String format) {
        if (date != null) {
            return date.format(DateTimeFormatter.ofPattern(format));
        } else {
            return "";
        }
    }

    public static Integer date2YYYYMMDD(LocalDate date) {
        if (date != null) {
            return Integer.parseInt(date.format(DateTimeFormatter.ofPattern(YYYYMMDD_STRING)));
        } else {
            return null;
        }
    }

    public static Integer date2YYYYMMDD(LocalDateTime date) {
        return date2YYYYMMDD(date.toLocalDate());
    }

    public static Integer date2YYYYMM(LocalDate date) {
        if (date != null) {
            return Integer.parseInt(date.format(DateTimeFormatter.ofPattern("yyyyMM")));
        } else {
            return null;
        }
    }

    public static Integer date2YYYYMM(LocalDateTime date) {
        return date2YYYYMM(date.toLocalDate());
    }

    public static LocalDateTime str2DateTime(String dateStr, String format) {
        if (dateStr != null) {
            return LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern(format));
        } else {
            return null;
        }
    }

    public static LocalDate str2Date(String dateStr, String format) {
        if (dateStr != null) {
            return LocalDate.parse(dateStr, DateTimeFormatter.ofPattern(format));
        } else {
            return null;
        }
    }

    public static LocalDateTime fromTimestamp(long timestamp) {
        Timestamp time = null;
        if (timestamp > 1655000000000L) {
            time = Timestamp.from(Instant.ofEpochMilli(timestamp));
        } else {
            time = Timestamp.from(Instant.ofEpochSecond(timestamp));
        }
        return time.toLocalDateTime();
    }

    public static Long stringToTimestamp(String strDatetime) throws ParseException {
        if (StringUtils.isEmpty(strDatetime)) {
            return null;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_MILLISECOND_STRING);
        return dateFormat.parse(strDatetime).getTime();
    }

    /**
     * yyyy-MM-dd HH:mm:ss
     *
     * @param strDatetime
     * @return
     * @throws ParseException
     */
    public static LocalDateTime stringToDatetime(String strDatetime) {
        return str2DateTime(strDatetime, DATE_FORMAT_SECOND_STRING);
    }

    /**
     * yyyy-MM-dd HH:mm:ss.zzz
     *
     * @param msDatetime
     * @return
     * @throws ParseException
     */
    public static LocalDateTime stringToDatetimeMS(String msDatetime) {
        return str2DateTime(msDatetime, DATE_FORMAT_MILLISECOND_STRING);
    }

    /**
     * 一年之后
     *
     * @return
     */
    public static LocalDateTime afterOneYear() {
        return LocalDateTime.now().plusYears(1);
    }

    public static LocalDateTime afterSomeDay(int dayAmount) {
        return LocalDateTime.now().plusDays(dayAmount);
    }

    public static LocalDateTime yesterday() {
        return LocalDateTime.now().minusDays(1);
    }

    public static LocalDateTime nextDate(LocalDateTime theDate) {
        return theDate.plusDays(1);
    }

    public static LocalDate monthFirstDate(LocalDate theDate) {
        return LocalDate.of(theDate.getYear(), theDate.getMonthValue(), 1);
    }

    public static LocalDate nextMonthFirstDate(LocalDate theDate) {
        LocalDate date = theDate.plusMonths(1);
        return LocalDate.of(date.getYear(), date.getMonthValue(), 1);
    }

    public static String monthFirstDateStr(LocalDate theDate) {
        LocalDate firstDate = monthFirstDate(theDate);
        return firstDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    public static String nextMonthFirstDateStr(LocalDate theDate) {
        LocalDate date = nextMonthFirstDate(theDate);
        return date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    public static void main(String[] args) {
//        LocalDateTime dateTime = LocalDateTime.now();
//        System.out.println((long) (dateTime.getYear()) * 10000000);
//        System.out.println(dateTime.getMonthValue() * 1000000);
//        System.out.println(dateTime.getDayOfMonth() * 10000);
//        System.out.println(dateTime.getHour() * 100);
//        System.out.println(dateTime.getMinute());

//        System.out.println(fromYYYYMMDDhhmm(202207092345L));
        System.out.println(String.format("%.3f", 90.7543));
//        long time = 202212292356L;
//        LocalDateTime dateTime = LocalDateTime.of(
//                (int) (time / 100000000),
//                (int) (time / 1000000 % 100),
//                (int) (time / 10000 % 100),
//                (int) (time / 100 % 100),
//                (int) (time % 100),
//                0, 0);

//        System.out.println(dateTime);
    }

}
